library(tidyverse)
Registered S3 methods overwritten by 'dbplyr':
method from
print.tbl_lazy
print.tbl_sql
── Attaching packages ──────────────────────────────────────────────────────────────── tidyverse 1.3.2 ──✔ ggplot2 3.3.6 ✔ purrr 0.3.4
✔ tibble 3.1.8 ✔ dplyr 1.0.9
✔ tidyr 1.2.0 ✔ stringr 1.4.0
✔ readr 2.1.2 ✔ forcats 0.5.1── Conflicts ─────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag() masks stats::lag()
library(gganimate)
library(ggtern)
Registered S3 methods overwritten by 'ggtern':
method from
grid.draw.ggplot ggplot2
plot.ggplot ggplot2
print.ggplot ggplot2
--
Remember to cite, run citation(package = 'ggtern') for further info.
--
Attaching package: ‘ggtern’
The following objects are masked from ‘package:ggplot2’:
aes, annotate, ggplot, ggplot_build, ggplot_gtable, ggplotGrob, ggsave, layer_data,
theme_bw, theme_classic, theme_dark, theme_gray, theme_light, theme_linedraw,
theme_minimal, theme_void
obp_dynatts_df <- read_csv("resources/3_obp_dynatts_df.csv")
Rows: 106657 Columns: 24── Column specification ─────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (2): SECCODE, ATT
dbl (20): NO, OBPLOTNO, VAL, SHAREBAL, BPROFIT, SPROFIT, OBPMINTPRICE, OBPMAXTPRICE, CBOVOLtdcs, CSO...
dttm (1): DATETIMEMLLS
date (1): DATE
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
obp_dynatts_df
OBPlots_df <- read_csv("resources/2_OBPlots_df.csv")
Rows: 106657 Columns: 12── Column specification ─────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (2): SECCODE, BUYSELL
dbl (9): NO, TIME, ORDERNO, ACTION, PRICE, VOLUME, TRADENO, TRADEPRICE, OBPLOTNO
date (1): DATE
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
OBPlots_df
obp_dynatts_no_df <- left_join(obp_dynatts_df,
OBPlots_df %>% select(NO, TIME),
by = "NO") %>%
mutate(TIMEm = as.character(as.integer(TIME / 100000)),
TIME = as.character(TIME / 1000)) %>%
select(NO, SECCODE, DATETIMEMLLS, DATE, TIME, TIMEm, OBPLOTNO,
ATT, VAL, SHAREBAL, BPROFIT, SPROFIT, OBPMINTPRICE, OBPMAXTPRICE,
CBOVOLtdcs, CSOVOLtdcs, BOVOLtdcs, SOVOLtdcs, BTVOLtdcs, STVOLtdcs,
CBOVOLobpcs, CSOVOLobpcs, BOVOLobpcs, SOVOLobpcs, BTVOLobpcs, STVOLobpcs)
obp_dynatts_no_df
obp_dynatts_no_price_df <- left_join(obp_dynatts_no_df,
OBPlots_df %>% select(NO, PRICE, TRADEPRICE, VOLUME),
by="NO")
obp_dynatts_no_price_df
temp_df <- obp_dynatts_no_df %>%
spread(key = ATT, value = VAL) %>%
select(TIME, TIMEm, NO, OBPLOTNO, SOVOL, SOVOLtdcs, SOVOLobpcs)
# filter(OBPLOTNO == 129)
temp_df
ggplot(data = temp_df) +
# geom_point(mapping = aes(x = NO, y = SOVOL), color = "red") +
# geom_point(mapping = aes(x = NO, y = SOVOLtdcs), color = "green") +
geom_point(mapping = aes(x = NO, y = SOVOLobpcs), color = "blue")

# sm - val median by second
temp_sm_df <- temp_df %>%
group_by(TIMEm) %>%
summarise(SOVOLobpcs = median(SOVOLobpcs))
temp_sm_df
ggplot(data = temp_sm_df) +
geom_point(mapping = aes(x = TIMEm, y = SOVOLobpcs), color = "blue")

obp_atts_by_obp_df <- read_csv("resources/4_obp_atts_by_obp_df.csv")
Rows: 2028 Columns: 8── Column specification ─────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (2): SECCODE, BUYSELLOBP
dbl (4): OBPLOTNO, BUYSELLYIELD, OBPTDVOLRATIO, MINMAXRATIO
lgl (1): TRADESNOTRADES
date (1): DATE
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
obp_atts_by_obp_df
obp_atts_by_obp_df %>% arrange(desc(MINMAXRATIO))
# obp_atts_by_obp_df %>% arrange(BUYSELLYIELD)
pbegin <- obp_dynatts_no_price_df %>%
.$DATETIMEMLLS %>%
min(.)
print(pbegin)
[1] "2007-10-08 10:30:00 UTC"
pend <- obp_dynatts_no_price_df %>%
.$DATETIMEMLLS %>%
max(.)
print(pend)
[1] "2007-10-08 17:45:00 UTC"
pcolor <- function(att, plotno) {
color = ""
if (plotno == plotno) {
if (att == 'BOVOL') color = "green"
else if (att == 'SOVOL') color = "red"
else if (att == 'BTVOL' | att == 'STVOL') color = "blue"
else color = "white"
} else {
if (att == 'BOVOL') color = "green"#"aquamarine"
else if (att == 'SOVOL') color = "red"#"coral"
else if (att == 'BTVOL' | att == 'STVOL') color = "blue" #"cadetblue1"
else color = "white"
}
# print(paste(att, plotno, color))
return(color)
}
td_df <- obp_dynatts_no_price_df %>%
filter((DATETIMEMLLS >= pbegin & DATETIMEMLLS <= pend) & (ATT == "BOVOL" | ATT == "SOVOL" | ATT == "BTVOL" | ATT == "STVOL") & PRICE > 2145.0 & PRICE < 2195.0) %>%
mutate(pcolor = map2(ATT, OBPLOTNO, ~pcolor(.x, .y)) %>% unlist())
td_df
# curplotno = 302
curplotno = 1869
# curplotno = 52
pbegin <- obp_dynatts_no_price_df %>%
filter(OBPLOTNO == curplotno) %>%
.$DATETIMEMLLS %>%
min(.)
pend <- obp_dynatts_no_price_df %>%
filter(OBPLOTNO == curplotno) %>%
.$DATETIMEMLLS %>%
max(.)
pcolor <- function(att, plotno) {
color = ""
if (plotno == curplotno) {
if (att == 'BOVOL') color = "green"
else if (att == 'SOVOL') color = "red"
else if (att == 'BTVOL' | att == 'STVOL') color = "#8031A7" #"blue"
else color = "white"
} else {
if (att == 'BOVOL') color = "aquamarine"
else if (att == 'SOVOL') color = "coral"
else if (att == 'BTVOL' | att == 'STVOL') color = "#004481" #"cadetblue1"
else color = "white"
}
# print(paste(att, plotno, color))
return(color)
}
pshape <- function(att, plotno) {
color = ""
if (plotno == curplotno) {
shape = 16
} else {
shape = 4
}
# print(paste(att, plotno, color))
return(shape)
}
psize <- function(att, plotno) {
color = ""
if (plotno == curplotno) {
size = 1.0
} else {
size = 0.5
}
# print(paste(att, plotno, color))
return(size)
}
plot_df_without_rep_by_vol <- obp_dynatts_no_price_df %>%
filter((DATETIMEMLLS >= pbegin & DATETIMEMLLS <= pend) & (ATT == "BOVOL" | ATT == "SOVOL" | ATT == "BTVOL" | ATT == "STVOL") & PRICE > 2145.0 & PRICE < 2205.0) %>%
mutate(pcolor = map2(ATT, OBPLOTNO, ~pcolor(.x, .y)) %>% unlist(),
pshape = map2(ATT, OBPLOTNO, ~pshape(.x, .y)) %>% unlist(),
psize = map2(ATT, OBPLOTNO, ~psize(.x, .y)) %>% unlist())
plot_df_without_rep_by_vol %>% filter(OBPLOTNO == curplotno)
# plot_df <- with(plot_df_without_rep_by_vol,
# plot_df_without_rep_by_vol[rep(1:nrow(plot_df_without_rep_by_vol),
# as.integer(log(VOLUME, base = 1.01)) + 1),])
plot_df <- plot_df_without_rep_by_vol
# dt1 <- td_df %>% filter(ATT != "BTVOL" & ATT != "STVOL")
# dt2 <- td_df %>% filter(ATT == "BTVOL" | ATT == "STVOL")
# ggplot() +
# geom_point(data = dt1, mapping = aes(x = TIME, y = PRICE), color = dt1$pcolor, shape = 4, size = 0.5) +
# geom_point(data = dt2, mapping = aes(x = TIME, y = PRICE), color = dt2$pcolor, shape = 4, size = 0.5)
dt11 <- plot_df %>% filter(OBPLOTNO != curplotno & ATT != "BTVOL" & ATT != "STVOL")
dt12 <- plot_df %>% filter(OBPLOTNO != curplotno & (ATT == "BTVOL" | ATT == "STVOL"))
dt21 <- plot_df %>% filter(OBPLOTNO == curplotno & ATT != "BTVOL" & ATT != "STVOL")
dt22 <- plot_df %>% filter(OBPLOTNO == curplotno & (ATT == "BTVOL" | ATT == "STVOL"))
ggplot() +
geom_point(data = dt11, mapping = aes(x = TIME, y = PRICE),
color = dt11$pcolor, shape = dt11$pshape, size = dt11$psize) +
geom_point(data = dt12, mapping = aes(x = TIME, y = PRICE),
color = dt12$pcolor, shape = dt12$pshape, size = dt12$psize) +
geom_point(data = dt21, mapping = aes(x = TIME, y = PRICE),
color = dt21$pcolor, shape = dt21$pshape, size = dt21$psize) +
geom_point(data = dt22, mapping = aes(x = TIME, y = PRICE),
color = dt22$pcolor, shape = dt22$pshape, size = dt22$psize)

dt_s <- plot_df %>% filter(OBPLOTNO != curplotno & ATT == "SOVOL")
dt_b <- plot_df %>% filter(OBPLOTNO != curplotno & ATT == "BOVOL")
dt_t <- plot_df %>% filter(OBPLOTNO != curplotno & (ATT == "BTVOL" | ATT == "STVOL"))
dt_cp_sb <- plot_df %>% filter(OBPLOTNO == curplotno & ATT != "BTVOL" & ATT != "STVOL")
dt_cp_t <- plot_df %>% filter(OBPLOTNO == curplotno & (ATT == "BTVOL" | ATT == "STVOL"))
# dt_s <- plot_df %>% filter(ATT == "SOVOL")
# dt_b <- plot_df %>% filter(ATT == "BOVOL")
# dt_t <- plot_df %>% filter(ATT == "BTVOL" | ATT == "STVOL")
# ggplot(dt_s, aes(x = NO, y = PRICE)) +
# stat_density2d(mapping = aes(fill = ..level..), alpha = .5,
# geom = "polygon", data = dt_s) +
# scale_fill_viridis_c() +
# # theme(legend.position = 'none') +
# scale_fill_distiller(palette = 'Reds')
# ggplot(dt_b, aes(x = NO, y = PRICE)) +
# stat_density2d(mapping = aes(fill = ..level..), alpha = .5,
# geom = "polygon", data = dt_b) +
# scale_fill_viridis_c() +
# # theme(legend.position = 'none') +
# scale_fill_distiller(palette = 'Greens')
ggplot(bind_rows(tibble(dt_s, gr = "s"), tibble(dt_b, gr = "b")), aes(x = NO, y = PRICE)) +
stat_density2d(geom = "polygon", aes(fill = gr, alpha = ..level..)) +
scale_fill_manual(values=c("s"="#FF0000", "b"="#00FF00")) +
geom_point(data = dt_t, mapping = aes(x = NO, y = PRICE),
color = dt_t$pcolor, shape = dt_t$pshape, size = dt_t$psize) +
geom_point(data = dt_cp_sb, mapping = aes(x = NO, y = PRICE),
color = dt_cp_sb$pcolor, shape = dt_cp_sb$pshape, size = dt_cp_sb$psize) +
geom_point(data = dt_cp_t, mapping = aes(x = NO, y = PRICE),
color = dt_cp_t$pcolor, shape = dt_cp_t$pshape, size = dt_cp_t$psize)

ggplot(bind_rows(tibble(dt_b, gr = "s"), tibble(dt_s, gr = "b")), aes(x = NO, y = PRICE)) +
stat_density2d(geom = "polygon", aes(fill = gr, alpha = ..level..)) +
scale_fill_manual(values=c("b"="#FF0000", "s"="#00FF00")) +
geom_point(data = dt_t, mapping = aes(x = NO, y = PRICE),
color = dt_t$pcolor, shape = dt_t$pshape, size = dt_t$psize) +
geom_point(data = dt_cp_sb, mapping = aes(x = NO, y = PRICE),
color = dt_cp_sb$pcolor, shape = dt_cp_sb$pshape, size = dt_cp_sb$psize) +
geom_point(data = dt_cp_t, mapping = aes(x = NO, y = PRICE),
color = dt_cp_t$pcolor, shape = dt_cp_t$pshape, size = dt_cp_t$psize)

ggplot(bind_rows(tibble(dt_s, gr = "s"), tibble(dt_b, gr = "b")), aes(x = NO, y = PRICE)) +
stat_density2d(geom = "density2d", aes(color = gr)) +
scale_color_manual(values=c("s"="#FF0000", "b"="#00FF00")) +
geom_point(data = dt_t, mapping = aes(x = NO, y = PRICE),
color = dt_t$pcolor, shape = dt_t$pshape, size = dt_t$psize) +
geom_point(data = dt_cp_sb, mapping = aes(x = NO, y = PRICE),
color = dt_cp_sb$pcolor, shape = dt_cp_sb$pshape, size = dt_cp_sb$psize) +
geom_point(data = dt_cp_t, mapping = aes(x = NO, y = PRICE),
color = dt_cp_t$pcolor, shape = dt_cp_t$pshape, size = dt_cp_t$psize) +
theme_bw()

td_first_30minute_df <- td_df %>%
filter(TIME < 1100000)
td_first_30minute_df
static_plot <- ggplot() +
geom_point(data = td_first_30minute_df,
mapping = aes(x = TIME, y = PRICE),
color = td_first_30minute_df$pcolor,
shape = 4,
size = 0.5)
static_plot

# animation <- static_plot +
# transition_states(NO, transition_length = 1, state_length = 1) +
# ease_aes('linear') +
# shadow_mark() +
# view_follow()
# animation
# obp30mins_gif <- animate(animation,
# fps = 10,
# duration = 10,
# width = 800, height = 400,
# renderer = gifski_renderer("./2gif/obp30mins.gif"))
LS0tDQp0aXRsZTogIk9CUGxvdHMiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpgYGB7cn0NCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShnZ2FuaW1hdGUpDQpsaWJyYXJ5KGdndGVybikNCmBgYA0KDQoNCmBgYHtyfQ0Kb2JwX2R5bmF0dHNfZGYgPC0gcmVhZF9jc3YoInJlc291cmNlcy8zX29icF9keW5hdHRzX2RmLmNzdiIpDQpvYnBfZHluYXR0c19kZg0KYGBgDQoNCmBgYHtyfQ0KT0JQbG90c19kZiA8LSByZWFkX2NzdigicmVzb3VyY2VzLzJfT0JQbG90c19kZi5jc3YiKQ0KT0JQbG90c19kZg0KYGBgDQoNCmBgYHtyfQ0Kb2JwX2R5bmF0dHNfbm9fZGYgPC0gbGVmdF9qb2luKG9icF9keW5hdHRzX2RmLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBPQlBsb3RzX2RmICU+JSBzZWxlY3QoTk8sIFRJTUUpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9ICJOTyIpICU+JSANCiAgbXV0YXRlKFRJTUVtID0gYXMuY2hhcmFjdGVyKGFzLmludGVnZXIoVElNRSAvIDEwMDAwMCkpLA0KICAgICAgICAgVElNRSA9IGFzLmNoYXJhY3RlcihUSU1FIC8gMTAwMCkpICU+JSANCiAgc2VsZWN0KE5PLCBTRUNDT0RFLCBEQVRFVElNRU1MTFMsIERBVEUsIFRJTUUsIFRJTUVtLCBPQlBMT1ROTywgDQogICAgICAgICBBVFQsIFZBTCwgU0hBUkVCQUwsIEJQUk9GSVQsIFNQUk9GSVQsIE9CUE1JTlRQUklDRSwgT0JQTUFYVFBSSUNFLA0KICAgICAgICAgQ0JPVk9MdGRjcywgQ1NPVk9MdGRjcywgQk9WT0x0ZGNzLCBTT1ZPTHRkY3MsIEJUVk9MdGRjcywgU1RWT0x0ZGNzLA0KICAgICAgICAgQ0JPVk9Mb2JwY3MsIENTT1ZPTG9icGNzLCBCT1ZPTG9icGNzLCBTT1ZPTG9icGNzLCBCVFZPTG9icGNzLCBTVFZPTG9icGNzKQ0Kb2JwX2R5bmF0dHNfbm9fZGYNCmBgYA0KDQpgYGB7cn0NCm9icF9keW5hdHRzX25vX3ByaWNlX2RmIDwtIGxlZnRfam9pbihvYnBfZHluYXR0c19ub19kZiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgT0JQbG90c19kZiAlPiUgc2VsZWN0KE5PLCBQUklDRSwgVFJBREVQUklDRSwgVk9MVU1FKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnk9Ik5PIikNCm9icF9keW5hdHRzX25vX3ByaWNlX2RmDQpgYGANCg0KYGBge3J9DQp0ZW1wX2RmIDwtIG9icF9keW5hdHRzX25vX2RmICU+JSANCiAgc3ByZWFkKGtleSA9IEFUVCwgdmFsdWUgPSBWQUwpICU+JSANCiAgc2VsZWN0KFRJTUUsIFRJTUVtLCBOTywgT0JQTE9UTk8sIFNPVk9MLCBTT1ZPTHRkY3MsIFNPVk9Mb2JwY3MpDQogICMgZmlsdGVyKE9CUExPVE5PID09IDEyOSkNCnRlbXBfZGYNCmBgYA0KDQpgYGB7cn0NCmdncGxvdChkYXRhID0gdGVtcF9kZikgKyANCiAgIyBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoeCA9IE5PLCB5ID0gU09WT0wpLCBjb2xvciA9ICJyZWQiKSArDQogICMgZ2VvbV9wb2ludChtYXBwaW5nID0gYWVzKHggPSBOTywgeSA9IFNPVk9MdGRjcyksIGNvbG9yID0gImdyZWVuIikgKw0KICBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoeCA9IE5PLCB5ID0gU09WT0xvYnBjcyksIGNvbG9yID0gImJsdWUiKQ0KYGBgDQoNCmBgYHtyfQ0KIyBzbSAtIHZhbCBtZWRpYW4gYnkgc2Vjb25kDQoNCnRlbXBfc21fZGYgPC0gdGVtcF9kZiAlPiUgDQogIGdyb3VwX2J5KFRJTUVtKSAlPiUgDQogIHN1bW1hcmlzZShTT1ZPTG9icGNzID0gbWVkaWFuKFNPVk9Mb2JwY3MpKQ0KdGVtcF9zbV9kZg0KYGBgDQoNCg0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IHRlbXBfc21fZGYpICsgDQogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyh4ID0gVElNRW0sIHkgPSBTT1ZPTG9icGNzKSwgY29sb3IgPSAiYmx1ZSIpDQpgYGANCg0KYGBge3J9DQpvYnBfYXR0c19ieV9vYnBfZGYgPC0gcmVhZF9jc3YoInJlc291cmNlcy80X29icF9hdHRzX2J5X29icF9kZi5jc3YiKQ0Kb2JwX2F0dHNfYnlfb2JwX2RmDQpgYGANCg0KYGBge3J9DQpvYnBfYXR0c19ieV9vYnBfZGYgJT4lIGFycmFuZ2UoZGVzYyhNSU5NQVhSQVRJTykpDQojIG9icF9hdHRzX2J5X29icF9kZiAlPiUgYXJyYW5nZShCVVlTRUxMWUlFTEQpDQpgYGANCg0KDQpgYGB7cn0NCnBiZWdpbiA8LSBvYnBfZHluYXR0c19ub19wcmljZV9kZiAlPiUgDQogIC4kREFURVRJTUVNTExTICU+JSANCiAgbWluKC4pDQpwcmludChwYmVnaW4pDQoNCnBlbmQgPC0gb2JwX2R5bmF0dHNfbm9fcHJpY2VfZGYgJT4lIA0KICAuJERBVEVUSU1FTUxMUyAlPiUgDQogIG1heCguKSANCnByaW50KHBlbmQpDQoNCnBjb2xvciA8LSBmdW5jdGlvbihhdHQsIHBsb3Rubykgew0KICBjb2xvciA9ICIiDQogIGlmIChwbG90bm8gPT0gcGxvdG5vKSB7DQogICAgaWYgKGF0dCA9PSAnQk9WT0wnKSBjb2xvciA9ICJncmVlbiINCiAgICBlbHNlIGlmIChhdHQgPT0gJ1NPVk9MJykgY29sb3IgPSAicmVkIg0KICAgIGVsc2UgaWYgKGF0dCA9PSAnQlRWT0wnIHwgYXR0ID09ICdTVFZPTCcpIGNvbG9yID0gImJsdWUiDQogICAgZWxzZSBjb2xvciA9ICJ3aGl0ZSINCiAgfSBlbHNlIHsNCiAgICBpZiAoYXR0ID09ICdCT1ZPTCcpIGNvbG9yID0gImdyZWVuIiMiYXF1YW1hcmluZSINCiAgICBlbHNlIGlmIChhdHQgPT0gJ1NPVk9MJykgY29sb3IgPSAicmVkIiMiY29yYWwiDQogICAgZWxzZSBpZiAoYXR0ID09ICdCVFZPTCcgfCBhdHQgPT0gJ1NUVk9MJykgY29sb3IgPSAiYmx1ZSIgIyJjYWRldGJsdWUxIg0KICAgIGVsc2UgY29sb3IgPSAid2hpdGUiDQogIH0NCiAgIyBwcmludChwYXN0ZShhdHQsIHBsb3RubywgY29sb3IpKQ0KICByZXR1cm4oY29sb3IpDQp9DQp0ZF9kZiA8LSBvYnBfZHluYXR0c19ub19wcmljZV9kZiAlPiUgDQogIGZpbHRlcigoREFURVRJTUVNTExTID49IHBiZWdpbiAmIERBVEVUSU1FTUxMUyA8PSBwZW5kKSAmIChBVFQgPT0gIkJPVk9MIiB8IEFUVCA9PSAiU09WT0wiIHwgQVRUID09ICJCVFZPTCIgfCBBVFQgPT0gIlNUVk9MIikgJiBQUklDRSA+IDIxNDUuMCAmIFBSSUNFIDwgMjE5NS4wKSAlPiUNCiAgbXV0YXRlKHBjb2xvciA9IG1hcDIoQVRULCBPQlBMT1ROTywgfnBjb2xvcigueCwgLnkpKSAlPiUgdW5saXN0KCkpDQp0ZF9kZg0KYGBgDQoNCmBgYHtyfQ0KIyBjdXJwbG90bm8gPSAzMDINCmN1cnBsb3RubyA9IDE4NjkNCiMgY3VycGxvdG5vID0gNTINCg0KcGJlZ2luIDwtIG9icF9keW5hdHRzX25vX3ByaWNlX2RmICU+JQ0KICBmaWx0ZXIoT0JQTE9UTk8gPT0gY3VycGxvdG5vKSAlPiUNCiAgLiREQVRFVElNRU1MTFMgJT4lDQogIG1pbiguKQ0KDQpwZW5kIDwtIG9icF9keW5hdHRzX25vX3ByaWNlX2RmICU+JQ0KICBmaWx0ZXIoT0JQTE9UTk8gPT0gY3VycGxvdG5vKSAlPiUNCiAgLiREQVRFVElNRU1MTFMgJT4lDQogIG1heCguKQ0KDQpwY29sb3IgPC0gZnVuY3Rpb24oYXR0LCBwbG90bm8pIHsNCiAgY29sb3IgPSAiIg0KICBpZiAocGxvdG5vID09IGN1cnBsb3Rubykgew0KICAgIGlmIChhdHQgPT0gJ0JPVk9MJykgY29sb3IgPSAiZ3JlZW4iDQogICAgZWxzZSBpZiAoYXR0ID09ICdTT1ZPTCcpIGNvbG9yID0gInJlZCINCiAgICBlbHNlIGlmIChhdHQgPT0gJ0JUVk9MJyB8IGF0dCA9PSAnU1RWT0wnKSBjb2xvciA9ICIjODAzMUE3IiAjImJsdWUiDQogICAgZWxzZSBjb2xvciA9ICJ3aGl0ZSINCiAgfSBlbHNlIHsNCiAgICBpZiAoYXR0ID09ICdCT1ZPTCcpIGNvbG9yID0gImFxdWFtYXJpbmUiDQogICAgZWxzZSBpZiAoYXR0ID09ICdTT1ZPTCcpIGNvbG9yID0gImNvcmFsIg0KICAgIGVsc2UgaWYgKGF0dCA9PSAnQlRWT0wnIHwgYXR0ID09ICdTVFZPTCcpIGNvbG9yID0gIiMwMDQ0ODEiICMiY2FkZXRibHVlMSINCiAgICBlbHNlIGNvbG9yID0gIndoaXRlIg0KICB9DQogICMgcHJpbnQocGFzdGUoYXR0LCBwbG90bm8sIGNvbG9yKSkNCiAgcmV0dXJuKGNvbG9yKQ0KfQ0KDQpwc2hhcGUgPC0gZnVuY3Rpb24oYXR0LCBwbG90bm8pIHsNCiAgY29sb3IgPSAiIg0KICBpZiAocGxvdG5vID09IGN1cnBsb3Rubykgew0KICAgIHNoYXBlID0gMTYNCiAgfSBlbHNlIHsNCiAgICBzaGFwZSA9IDQNCiAgfQ0KICAjIHByaW50KHBhc3RlKGF0dCwgcGxvdG5vLCBjb2xvcikpDQogIHJldHVybihzaGFwZSkNCn0NCg0KcHNpemUgPC0gZnVuY3Rpb24oYXR0LCBwbG90bm8pIHsNCiAgY29sb3IgPSAiIg0KICBpZiAocGxvdG5vID09IGN1cnBsb3Rubykgew0KICAgIHNpemUgPSAxLjANCiAgfSBlbHNlIHsNCiAgICBzaXplID0gMC41DQogIH0NCiAgIyBwcmludChwYXN0ZShhdHQsIHBsb3RubywgY29sb3IpKQ0KICByZXR1cm4oc2l6ZSkNCn0NCg0KcGxvdF9kZl93aXRob3V0X3JlcF9ieV92b2wgPC0gb2JwX2R5bmF0dHNfbm9fcHJpY2VfZGYgJT4lIA0KICBmaWx0ZXIoKERBVEVUSU1FTUxMUyA+PSBwYmVnaW4gJiBEQVRFVElNRU1MTFMgPD0gcGVuZCkgJiAoQVRUID09ICJCT1ZPTCIgfCBBVFQgPT0gIlNPVk9MIiB8IEFUVCA9PSAiQlRWT0wiIHwgQVRUID09ICJTVFZPTCIpICYgUFJJQ0UgPiAyMTQ1LjAgJiBQUklDRSA8IDIyMDUuMCkgJT4lDQogIG11dGF0ZShwY29sb3IgPSBtYXAyKEFUVCwgT0JQTE9UTk8sIH5wY29sb3IoLngsIC55KSkgJT4lIHVubGlzdCgpLA0KICAgICAgICAgcHNoYXBlID0gbWFwMihBVFQsIE9CUExPVE5PLCB+cHNoYXBlKC54LCAueSkpICU+JSB1bmxpc3QoKSwNCiAgICAgICAgIHBzaXplID0gbWFwMihBVFQsIE9CUExPVE5PLCB+cHNpemUoLngsIC55KSkgJT4lIHVubGlzdCgpKQ0KcGxvdF9kZl93aXRob3V0X3JlcF9ieV92b2wgJT4lIGZpbHRlcihPQlBMT1ROTyA9PSBjdXJwbG90bm8pDQpgYGANCg0KYGBge3J9DQojIHBsb3RfZGYgPC0gIHdpdGgocGxvdF9kZl93aXRob3V0X3JlcF9ieV92b2wsDQojICAgICAgICAgICAgICAgICAgcGxvdF9kZl93aXRob3V0X3JlcF9ieV92b2xbcmVwKDE6bnJvdyhwbG90X2RmX3dpdGhvdXRfcmVwX2J5X3ZvbCksDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzLmludGVnZXIobG9nKFZPTFVNRSwgYmFzZSA9IDEuMDEpKSArIDEpLF0pDQpwbG90X2RmIDwtICBwbG90X2RmX3dpdGhvdXRfcmVwX2J5X3ZvbA0KYGBgDQoNCg0KYGBge3J9DQojIGR0MSA8LSB0ZF9kZiAlPiUgZmlsdGVyKEFUVCAhPSAiQlRWT0wiICYgQVRUICE9ICJTVFZPTCIpDQojIGR0MiA8LSB0ZF9kZiAlPiUgZmlsdGVyKEFUVCA9PSAiQlRWT0wiIHwgQVRUID09ICJTVFZPTCIpDQojIGdncGxvdCgpICsgDQojICAgZ2VvbV9wb2ludChkYXRhID0gZHQxLCBtYXBwaW5nID0gYWVzKHggPSBUSU1FLCB5ID0gUFJJQ0UpLCBjb2xvciA9IGR0MSRwY29sb3IsIHNoYXBlID0gNCwgc2l6ZSA9IDAuNSkgKw0KIyAgIGdlb21fcG9pbnQoZGF0YSA9IGR0MiwgbWFwcGluZyA9IGFlcyh4ID0gVElNRSwgeSA9IFBSSUNFKSwgY29sb3IgPSBkdDIkcGNvbG9yLCBzaGFwZSA9IDQsIHNpemUgPSAwLjUpDQpgYGANCg0KYGBge3J9DQpkdDExIDwtIHBsb3RfZGYgJT4lIGZpbHRlcihPQlBMT1ROTyAhPSBjdXJwbG90bm8gJiBBVFQgIT0gIkJUVk9MIiAmIEFUVCAhPSAiU1RWT0wiKQ0KZHQxMiA8LSBwbG90X2RmICU+JSBmaWx0ZXIoT0JQTE9UTk8gIT0gY3VycGxvdG5vICYgKEFUVCA9PSAiQlRWT0wiIHwgQVRUID09ICJTVFZPTCIpKQ0KZHQyMSA8LSBwbG90X2RmICU+JSBmaWx0ZXIoT0JQTE9UTk8gPT0gY3VycGxvdG5vICYgQVRUICE9ICJCVFZPTCIgJiBBVFQgIT0gIlNUVk9MIikNCmR0MjIgPC0gcGxvdF9kZiAlPiUgZmlsdGVyKE9CUExPVE5PID09IGN1cnBsb3RubyAmIChBVFQgPT0gIkJUVk9MIiB8IEFUVCA9PSAiU1RWT0wiKSkNCmdncGxvdCgpICsgDQogIGdlb21fcG9pbnQoZGF0YSA9IGR0MTEsIG1hcHBpbmcgPSBhZXMoeCA9IFRJTUUsIHkgPSBQUklDRSksIA0KICAgICAgICAgICAgIGNvbG9yID0gZHQxMSRwY29sb3IsIHNoYXBlID0gZHQxMSRwc2hhcGUsIHNpemUgPSBkdDExJHBzaXplKSArIA0KICBnZW9tX3BvaW50KGRhdGEgPSBkdDEyLCBtYXBwaW5nID0gYWVzKHggPSBUSU1FLCB5ID0gUFJJQ0UpLCANCiAgICAgICAgICAgICBjb2xvciA9IGR0MTIkcGNvbG9yLCBzaGFwZSA9IGR0MTIkcHNoYXBlLCBzaXplID0gZHQxMiRwc2l6ZSkgKyANCiAgZ2VvbV9wb2ludChkYXRhID0gZHQyMSwgbWFwcGluZyA9IGFlcyh4ID0gVElNRSwgeSA9IFBSSUNFKSwgDQogICAgICAgICAgICAgY29sb3IgPSBkdDIxJHBjb2xvciwgc2hhcGUgPSBkdDIxJHBzaGFwZSwgc2l6ZSA9IGR0MjEkcHNpemUpICsgDQogIGdlb21fcG9pbnQoZGF0YSA9IGR0MjIsIG1hcHBpbmcgPSBhZXMoeCA9IFRJTUUsIHkgPSBQUklDRSksIA0KICAgICAgICAgICAgIGNvbG9yID0gZHQyMiRwY29sb3IsIHNoYXBlID0gZHQyMiRwc2hhcGUsIHNpemUgPSBkdDIyJHBzaXplKQ0KYGBgDQoNCmBgYHtyfQ0KZHRfcyA8LSBwbG90X2RmICU+JSBmaWx0ZXIoT0JQTE9UTk8gIT0gY3VycGxvdG5vICYgQVRUID09ICJTT1ZPTCIpDQpkdF9iIDwtIHBsb3RfZGYgJT4lIGZpbHRlcihPQlBMT1ROTyAhPSBjdXJwbG90bm8gJiBBVFQgPT0gIkJPVk9MIikNCmR0X3QgPC0gcGxvdF9kZiAlPiUgZmlsdGVyKE9CUExPVE5PICE9IGN1cnBsb3RubyAmIChBVFQgPT0gIkJUVk9MIiB8IEFUVCA9PSAiU1RWT0wiKSkNCmR0X2NwX3NiIDwtIHBsb3RfZGYgJT4lIGZpbHRlcihPQlBMT1ROTyA9PSBjdXJwbG90bm8gJiBBVFQgIT0gIkJUVk9MIiAmIEFUVCAhPSAiU1RWT0wiKQ0KZHRfY3BfdCA8LSBwbG90X2RmICU+JSBmaWx0ZXIoT0JQTE9UTk8gPT0gY3VycGxvdG5vICYgKEFUVCA9PSAiQlRWT0wiIHwgQVRUID09ICJTVFZPTCIpKQ0KDQojIGR0X3MgPC0gcGxvdF9kZiAlPiUgZmlsdGVyKEFUVCA9PSAiU09WT0wiKQ0KIyBkdF9iIDwtIHBsb3RfZGYgJT4lIGZpbHRlcihBVFQgPT0gIkJPVk9MIikNCiMgZHRfdCA8LSBwbG90X2RmICU+JSBmaWx0ZXIoQVRUID09ICJCVFZPTCIgfCBBVFQgPT0gIlNUVk9MIikNCg0KYGBgDQoNCmBgYHtyfQ0KIyBnZ3Bsb3QoZHRfcywgYWVzKHggPSBOTywgeSA9IFBSSUNFKSkgKw0KIyAgIHN0YXRfZGVuc2l0eTJkKG1hcHBpbmcgPSBhZXMoZmlsbCA9IC4ubGV2ZWwuLiksIGFscGhhID0gLjUsDQojICAgICAgICAgICAgICAgICAgZ2VvbSA9ICJwb2x5Z29uIiwgZGF0YSA9IGR0X3MpICsgDQojICAgc2NhbGVfZmlsbF92aXJpZGlzX2MoKSArIA0KIyAgICMgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gJ25vbmUnKSArDQojICAgc2NhbGVfZmlsbF9kaXN0aWxsZXIocGFsZXR0ZSA9ICdSZWRzJykNCmBgYA0KDQpgYGB7cn0NCiMgZ2dwbG90KGR0X2IsIGFlcyh4ID0gTk8sIHkgPSBQUklDRSkpICsNCiMgICBzdGF0X2RlbnNpdHkyZChtYXBwaW5nID0gYWVzKGZpbGwgPSAuLmxldmVsLi4pLCBhbHBoYSA9IC41LA0KIyAgICAgICAgICAgICAgICAgIGdlb20gPSAicG9seWdvbiIsIGRhdGEgPSBkdF9iKSArIA0KIyAgIHNjYWxlX2ZpbGxfdmlyaWRpc19jKCkgKyANCiMgICAjIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICdub25lJykgKw0KIyAgIHNjYWxlX2ZpbGxfZGlzdGlsbGVyKHBhbGV0dGUgPSAnR3JlZW5zJykNCmBgYA0KDQoNCmBgYHtyfQ0KZ2dwbG90KGJpbmRfcm93cyh0aWJibGUoZHRfcywgZ3IgPSAicyIpLCB0aWJibGUoZHRfYiwgZ3IgPSAiYiIpKSwgYWVzKHggPSBOTywgeSA9IFBSSUNFKSkgKw0KICBzdGF0X2RlbnNpdHkyZChnZW9tID0gInBvbHlnb24iLCBhZXMoZmlsbCA9IGdyLCBhbHBoYSA9IC4ubGV2ZWwuLikpICsgDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jKCJzIj0iI0ZGMDAwMCIsICJiIj0iIzAwRkYwMCIpKSArDQogIGdlb21fcG9pbnQoZGF0YSA9IGR0X3QsIG1hcHBpbmcgPSBhZXMoeCA9IE5PLCB5ID0gUFJJQ0UpLCANCiAgICAgICAgICAgICBjb2xvciA9IGR0X3QkcGNvbG9yLCBzaGFwZSA9IGR0X3QkcHNoYXBlLCBzaXplID0gZHRfdCRwc2l6ZSkgKw0KICBnZW9tX3BvaW50KGRhdGEgPSBkdF9jcF9zYiwgbWFwcGluZyA9IGFlcyh4ID0gTk8sIHkgPSBQUklDRSksIA0KICAgICAgICAgICAgIGNvbG9yID0gZHRfY3Bfc2IkcGNvbG9yLCBzaGFwZSA9IGR0X2NwX3NiJHBzaGFwZSwgc2l6ZSA9IGR0X2NwX3NiJHBzaXplKSArDQogIGdlb21fcG9pbnQoZGF0YSA9IGR0X2NwX3QsIG1hcHBpbmcgPSBhZXMoeCA9IE5PLCB5ID0gUFJJQ0UpLCANCiAgICAgICAgICAgICBjb2xvciA9IGR0X2NwX3QkcGNvbG9yLCBzaGFwZSA9IGR0X2NwX3QkcHNoYXBlLCBzaXplID0gZHRfY3BfdCRwc2l6ZSkNCmBgYA0KDQpgYGB7cn0NCmdncGxvdChiaW5kX3Jvd3ModGliYmxlKGR0X2IsIGdyID0gInMiKSwgdGliYmxlKGR0X3MsIGdyID0gImIiKSksIGFlcyh4ID0gTk8sIHkgPSBQUklDRSkpICsNCiAgc3RhdF9kZW5zaXR5MmQoZ2VvbSA9ICJwb2x5Z29uIiwgYWVzKGZpbGwgPSBnciwgYWxwaGEgPSAuLmxldmVsLi4pKSArIA0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9YygiYiI9IiNGRjAwMDAiLCAicyI9IiMwMEZGMDAiKSkgKw0KICBnZW9tX3BvaW50KGRhdGEgPSBkdF90LCBtYXBwaW5nID0gYWVzKHggPSBOTywgeSA9IFBSSUNFKSwgDQogICAgICAgICAgICAgY29sb3IgPSBkdF90JHBjb2xvciwgc2hhcGUgPSBkdF90JHBzaGFwZSwgc2l6ZSA9IGR0X3QkcHNpemUpICsNCiAgZ2VvbV9wb2ludChkYXRhID0gZHRfY3Bfc2IsIG1hcHBpbmcgPSBhZXMoeCA9IE5PLCB5ID0gUFJJQ0UpLCANCiAgICAgICAgICAgICBjb2xvciA9IGR0X2NwX3NiJHBjb2xvciwgc2hhcGUgPSBkdF9jcF9zYiRwc2hhcGUsIHNpemUgPSBkdF9jcF9zYiRwc2l6ZSkgKw0KICBnZW9tX3BvaW50KGRhdGEgPSBkdF9jcF90LCBtYXBwaW5nID0gYWVzKHggPSBOTywgeSA9IFBSSUNFKSwgDQogICAgICAgICAgICAgY29sb3IgPSBkdF9jcF90JHBjb2xvciwgc2hhcGUgPSBkdF9jcF90JHBzaGFwZSwgc2l6ZSA9IGR0X2NwX3QkcHNpemUpDQpgYGANCg0KYGBge3J9DQpnZ3Bsb3QoYmluZF9yb3dzKHRpYmJsZShkdF9zLCBnciA9ICJzIiksIHRpYmJsZShkdF9iLCBnciA9ICJiIikpLCBhZXMoeCA9IE5PLCB5ID0gUFJJQ0UpKSArDQogIHN0YXRfZGVuc2l0eTJkKGdlb20gPSAiZGVuc2l0eTJkIiwgYWVzKGNvbG9yID0gZ3IpKSArIA0KICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWMoInMiPSIjRkYwMDAwIiwgImIiPSIjMDBGRjAwIikpICsNCiAgZ2VvbV9wb2ludChkYXRhID0gZHRfdCwgbWFwcGluZyA9IGFlcyh4ID0gTk8sIHkgPSBQUklDRSksIA0KICAgICAgICAgICAgIGNvbG9yID0gZHRfdCRwY29sb3IsIHNoYXBlID0gZHRfdCRwc2hhcGUsIHNpemUgPSBkdF90JHBzaXplKSArDQogIGdlb21fcG9pbnQoZGF0YSA9IGR0X2NwX3NiLCBtYXBwaW5nID0gYWVzKHggPSBOTywgeSA9IFBSSUNFKSwgDQogICAgICAgICAgICAgY29sb3IgPSBkdF9jcF9zYiRwY29sb3IsIHNoYXBlID0gZHRfY3Bfc2IkcHNoYXBlLCBzaXplID0gZHRfY3Bfc2IkcHNpemUpICsNCiAgZ2VvbV9wb2ludChkYXRhID0gZHRfY3BfdCwgbWFwcGluZyA9IGFlcyh4ID0gTk8sIHkgPSBQUklDRSksIA0KICAgICAgICAgICAgIGNvbG9yID0gZHRfY3BfdCRwY29sb3IsIHNoYXBlID0gZHRfY3BfdCRwc2hhcGUsIHNpemUgPSBkdF9jcF90JHBzaXplKSArDQogIHRoZW1lX2J3KCkNCmBgYA0KDQpgYGB7cn0NCnRkX2ZpcnN0XzMwbWludXRlX2RmIDwtIHRkX2RmICU+JSANCiAgZmlsdGVyKFRJTUUgPCAxMTAwMDAwKQ0KdGRfZmlyc3RfMzBtaW51dGVfZGYNCmBgYA0KDQpgYGB7cn0NCnN0YXRpY19wbG90IDwtIGdncGxvdCgpICsgDQogIGdlb21fcG9pbnQoZGF0YSA9IHRkX2ZpcnN0XzMwbWludXRlX2RmLCANCiAgICAgICAgICAgICBtYXBwaW5nID0gYWVzKHggPSBUSU1FLCB5ID0gUFJJQ0UpLCANCiAgICAgICAgICAgICBjb2xvciA9IHRkX2ZpcnN0XzMwbWludXRlX2RmJHBjb2xvciwgDQogICAgICAgICAgICAgc2hhcGUgPSA0LCANCiAgICAgICAgICAgICBzaXplID0gMC41KQ0Kc3RhdGljX3Bsb3QNCmBgYA0KDQpgYGB7cn0NCg0KYGBgDQoNCg0KYGBge3J9DQojIGFuaW1hdGlvbiA8LSBzdGF0aWNfcGxvdCArDQojICAgdHJhbnNpdGlvbl9zdGF0ZXMoTk8sIHRyYW5zaXRpb25fbGVuZ3RoID0gMSwgc3RhdGVfbGVuZ3RoID0gMSkgKw0KIyAgIGVhc2VfYWVzKCdsaW5lYXInKSArDQojICAgc2hhZG93X21hcmsoKSArDQojICAgdmlld19mb2xsb3coKQ0KIyBhbmltYXRpb24NCmBgYA0KDQpgYGB7cn0NCiMgb2JwMzBtaW5zX2dpZiA8LSBhbmltYXRlKGFuaW1hdGlvbiwgDQojICAgICAgICAgICAgICAgICAgZnBzID0gMTAsIA0KIyAgICAgICAgICAgICAgICAgIGR1cmF0aW9uID0gMTAsDQojICAgICAgICAgICAgICAgICAgd2lkdGggPSA4MDAsIGhlaWdodCA9IDQwMCwgDQojICAgICAgICAgICAgICAgICAgcmVuZGVyZXIgPSBnaWZza2lfcmVuZGVyZXIoIi4vMmdpZi9vYnAzMG1pbnMuZ2lmIikpDQpgYGANCg0K